﻿// Decompiled with JetBrains decompiler
// Type: Netick.CodeGen.Processor
// Assembly: Netick.CodeGen, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 95965C71-875F-44B8-BA79-93A19C7D6A17
// Assembly location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Editor\Netick.CodeGen.dll

using Mono.Cecil;
using Mono.Cecil.Cil;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;

#nullable disable
namespace Netick.CodeGen;

public static class Processor
{
  public static void ProcessAssembly(ICodeGenUser weaver, string assemblyFullPath)
  {
    weaver.Log((object) "Netick CodeGen: started");
    string directoryName = Path.GetDirectoryName(assemblyFullPath);
    Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
    bool flag = false;
    List<string> stringList = new List<string>();
    foreach (Assembly assembly1 in assemblies)
    {
      if (assembly1.GetName().Name == Path.GetFileNameWithoutExtension(assemblyFullPath))
      {
        flag = true;
        foreach (AssemblyName referencedAssembly in assembly1.GetReferencedAssemblies())
        {
          Assembly assembly2 = Assembly.Load(referencedAssembly);
          string name = assembly2.GetName().Name;
          if (name != "" && name != null && assembly2.Location != null && assembly2.Location != "")
            stringList.Add(assembly2.Location);
        }
      }
    }
    if (!flag)
    {
      foreach (Assembly assembly in assemblies)
      {
        try
        {
          if (!(assembly.ManifestModule is ModuleBuilder))
          {
            string name = assembly.GetName().Name;
            if (name != "")
            {
              if (name != null)
                stringList.Add(Assembly.Load(assembly.GetName().Name).Location);
            }
          }
        }
        catch (FileNotFoundException ex)
        {
        }
      }
    }
    if (!stringList.Contains(assemblyFullPath))
      stringList.Add(assemblyFullPath);
    string fileName = Path.GetFileName(assemblyFullPath);
    ILPostProcessCompiledAssembly compiledAssembly = new ILPostProcessCompiledAssembly(fileName, stringList.ToArray(), (string[]) null, directoryName);
    bool didProcess;
    ILPostProcessResult postProcessResult = Processor.BeforeProcess(weaver, compiledAssembly, out didProcess);
    if (postProcessResult != null && postProcessResult.Diagnostics.Count > 0)
    {
      weaver.LogError((object) ("Netick CodeGen failed to run on " + compiledAssembly.Name));
      foreach (DiagnosticMessage diagnostic in postProcessResult.Diagnostics)
        weaver.LogError((object) $"{"ILPostProcessor"} Error - {diagnostic.MessageData} {diagnostic.File}:{diagnostic.Line}");
    }
    else
      weaver.Log((object) "Netick CodeGen: done");
    if (!didProcess)
      return;
    Processor.WriteAssembly(postProcessResult.InMemoryAssembly, directoryName, fileName);
  }

  private static void WriteAssembly(
    InMemoryAssembly inMemoryAssembly,
    string outputPath,
    string assName)
  {
    if (inMemoryAssembly == null)
      throw new ArgumentException("InMemoryAssembly has never been accessed or modified");
    string path1 = Path.Combine(outputPath, assName);
    string path2 = Path.GetFileNameWithoutExtension(assName) + ".pdb";
    string path3 = Path.Combine(outputPath, path2);
    File.WriteAllBytes(path1, inMemoryAssembly.PeData);
    byte[] pdbData = inMemoryAssembly.PdbData;
    File.WriteAllBytes(path3, pdbData);
  }

  private static ILPostProcessResult BeforeProcess(
    ICodeGenUser weaver,
    ILPostProcessCompiledAssembly compiledAssembly,
    out bool didProcess)
  {
    NetickILProcessor netickIlProcessor = new NetickILProcessor();
    List<DiagnosticMessage> diagnostics = new List<DiagnosticMessage>();
    AssemblyDefinition assemblyDefinition = Processor.AssemblyDefinitionFor(compiledAssembly);
    didProcess = false;
    if (assemblyDefinition == null)
    {
      diagnostics.AddError("Cannot read assembly definition: " + compiledAssembly.Name);
      return (ILPostProcessResult) null;
    }
    if (assemblyDefinition.MainModule != null)
    {
      weaver.Init(assemblyDefinition.MainModule);
      netickIlProcessor.Init(weaver, assemblyDefinition.MainModule);
      didProcess = netickIlProcessor.ProcessAssembly(assemblyDefinition);
    }
    else
      diagnostics.AddError("Cannot get main module from assembly definition: " + compiledAssembly.Name);
    return Processor.GetResults(diagnostics, assemblyDefinition);
  }

  private static ILPostProcessResult GetResults(
    List<DiagnosticMessage> diagnostics,
    AssemblyDefinition assemblyDefinition,
    bool process = true)
  {
    MemoryStream memoryStream1 = new MemoryStream();
    MemoryStream memoryStream2 = new MemoryStream();
    WriterParameters writerParameters = new WriterParameters()
    {
      SymbolWriterProvider = (ISymbolWriterProvider) new PortablePdbWriterProvider(),
      SymbolStream = (Stream) memoryStream2,
      WriteSymbols = true
    };
    if (process)
      assemblyDefinition.Write((Stream) memoryStream1, writerParameters);
    return new ILPostProcessResult(new InMemoryAssembly(memoryStream1.ToArray(), memoryStream2.ToArray()), diagnostics);
  }

  private static AssemblyDefinition AssemblyDefinitionFor(
    ILPostProcessCompiledAssembly compiledAssembly)
  {
    PostProcessorAssemblyResolver assemblyResolver = new PostProcessorAssemblyResolver(compiledAssembly);
    ReaderParameters readerParameters = new ReaderParameters()
    {
      SymbolStream = (Stream) new MemoryStream(compiledAssembly.InMemoryAssembly.PdbData),
      SymbolReaderProvider = (ISymbolReaderProvider) new PortablePdbReaderProvider(),
      AssemblyResolver = (IAssemblyResolver) assemblyResolver,
      ReflectionImporterProvider = (IReflectionImporterProvider) new PostProcessorReflectionImporterProvider(),
      ReadingMode = (ReadingMode) 1
    };
    AssemblyDefinition assemblyDefinition = AssemblyDefinition.ReadAssembly((Stream) new MemoryStream(compiledAssembly.InMemoryAssembly.PeData), readerParameters);
    assemblyResolver.AddAssemblyDefinitionBeingOperatedOn(assemblyDefinition);
    return assemblyDefinition;
  }
}
